import os
from PyQt6.QtWidgets import (
    QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QPushButton, QSlider, QFrame, QFileDialog, QListWidget, QLabel,
    QStyle, QListWidgetItem, QMenu
)
from PyQt6.QtCore import Qt, QSettings, pyqtSignal, QTimer, QCoreApplication, QEvent, QObject
from PyQt6.QtGui import QIcon, QMouseEvent, QShortcut, QKeySequence

from core.player import PlayerCore
from database.history import HistoryDatabase

class ClickableOverlay(QWidget):
    double_clicked = pyqtSignal()
    clicked = pyqtSignal()
    mouse_moved = pyqtSignal() # 新增：鼠标移动信号

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground, True)
        self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, False)
        self.setMouseTracking(True) # 启用鼠标跟踪，以便接收mouseMoveEvent
        self.raise_()

        self._single_click_timer = QTimer(self)
        self._single_click_timer.setInterval(250)
        self._single_click_timer.setSingleShot(True)
        self._single_click_timer.timeout.connect(self._emit_single_click)

    def mousePressEvent(self, event: QMouseEvent):
        if event.button() == Qt.MouseButton.LeftButton:
            if self._single_click_timer.isActive():
                self._single_click_timer.stop()
            else:
                self._single_click_timer.start()
            event.accept()
        else:
            super().mousePressEvent(event)

    def mouseDoubleClickEvent(self, event: QMouseEvent):
        if self._single_click_timer.isActive():
            self._single_click_timer.stop()
        self.double_clicked.emit()
        event.accept()

    def mouseMoveEvent(self, event: QMouseEvent):
        """当鼠标在覆盖层上移动时，发出mouse_moved信号"""
        self.mouse_moved.emit()
        super().mouseMoveEvent(event) # 继续将事件传递给父级，以防万一

    def _emit_single_click(self):
        self.clicked.emit()

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("我的媒体播放器")

        # 标记控制条是否可见，确保在任何UI操作前初始化
        self._controls_visible = True

        self.settings = QSettings(QCoreApplication.organizationName(), QCoreApplication.applicationName())
        self.player = PlayerCore(self)
        self.db = HistoryDatabase()

        self._current_playlist_index = -1 # 当前播放列表的索引
        self._current_playlist = [] # 当前加载的播放列表内容

        self._create_ui()
        self._connect_signals()
        self._create_shortcuts()

        self._restore_window_state()
        self._load_stylesheet() # 确保样式表在UI创建后加载

        # 自动隐藏控制条的计时器
        self._hide_controls_timer = QTimer(self)
        self._hide_controls_timer.setInterval(3000) # 3秒不活动后隐藏
        self._hide_controls_timer.setSingleShot(True)
        self._hide_controls_timer.timeout.connect(self._hide_controls)

        # 仅在需要时安装事件过滤器，视频区域的鼠标移动现在由ClickableOverlay处理
        self.installEventFilter(self)

    def _create_ui(self):
        style = self.style()
        self.setWindowIcon(QIcon(style.standardIcon(QStyle.StandardPixmap.SP_MediaPlay)))

        # 视频播放区域
        self.video_frame = QFrame()
        self.video_frame.setObjectName("videoFrame") # 添加对象名方便QSS
        self.overlay = ClickableOverlay(self.video_frame)
        self.overlay.setGeometry(0, 0, self.video_frame.width(), self.video_frame.height())
        self.overlay.double_clicked.connect(self.toggle_fullscreen)
        self.overlay.raise_()

        # 控制按钮和滑块
        self.open_file_button = QPushButton("打开文件")
        self.add_to_playlist_button = QPushButton("添加到播放列表")
        self.play_pause_button = QPushButton()
        self.stop_button = QPushButton()
        self.prev_button = QPushButton() # 上一曲
        self.next_button = QPushButton() # 下一曲
        self.time_label = QLabel("00:00:00 / 00:00:00")
        self.position_slider = QSlider(Qt.Orientation.Horizontal)
        self.volume_slider = QSlider(Qt.Orientation.Horizontal)
        self.volume_label = QLabel("音量:") # 设为实例变量

        # 历史记录和播放列表区域
        self.history_list_widget = QListWidget()
        self.history_list_widget.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) # 允许自定义右键菜单
        self.history_list_widget.customContextMenuRequested.connect(self._show_history_context_menu)

        self.playlist_list_widget = QListWidget()
        self.playlist_list_widget.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) # 允许自定义右键菜单
        self.playlist_list_widget.customContextMenuRequested.connect(self._show_playlist_context_menu)

        # 设置图标
        self.play_pause_button.setIcon(style.standardIcon(QStyle.StandardPixmap.SP_MediaPlay))
        self.stop_button.setIcon(style.standardIcon(QStyle.StandardPixmap.SP_MediaStop))
        self.prev_button.setIcon(style.standardIcon(QStyle.StandardPixmap.SP_MediaSkipBackward))
        self.next_button.setIcon(style.standardIcon(QStyle.StandardPixmap.SP_MediaSkipForward))

        # 设置滑块范围和初始值
        self.position_slider.setRange(0, 1000)
        self.position_slider.setToolTip("播放进度")
        self.volume_slider.setRange(0, 100)
        self.volume_slider.setValue(self.player.get_volume())
        self.volume_slider.setToolTip("音量")
        self.volume_slider.setMaximumWidth(150)

        # 设置列表宽度
        self.history_list_widget.setMinimumWidth(200) # 最小宽度
        self.history_list_widget.setMaximumWidth(300) # 最大宽度
        self.playlist_list_widget.setMinimumWidth(200) # 最小宽度
        self.playlist_list_widget.setMaximumWidth(300) # 最大宽度

        # 加载初始数据
        self.load_history_ui()
        self.load_playlist_ui()

        # 新增：控制条的容器 Widget
        self.controls_container = QWidget(self) # 创建一个QWidget来承载所有控制条部件
        self.controls_container.setObjectName("controlsContainer") # 可选，用于QSS样式
        controls_layout = QHBoxLayout(self.controls_container) # 设置其布局

        # 将所有控制条部件添加到容器的布局中
        controls_layout.addWidget(self.open_file_button)
        controls_layout.addWidget(self.add_to_playlist_button)
        controls_layout.addWidget(self.prev_button)
        controls_layout.addWidget(self.play_pause_button)
        controls_layout.addWidget(self.next_button)
        controls_layout.addWidget(self.stop_button)
        controls_layout.addWidget(self.position_slider)
        controls_layout.addWidget(self.time_label)
        controls_layout.addWidget(self.volume_label)
        controls_layout.addWidget(self.volume_slider)

        # 主要的垂直布局，包含视频和控制条容器
        self.main_v_layout = QVBoxLayout()
        self.main_v_layout.addWidget(self.video_frame, 1) # 视频区域占据更多空间
        self.main_v_layout.addWidget(self.controls_container) # 将整个控制条容器添加到主布局

        # 右侧面板布局，包含历史记录和播放列表
        self.right_panel_layout = QVBoxLayout()
        self.history_label = QLabel("播放历史:")
        self.right_panel_layout.addWidget(self.history_label)
        self.right_panel_layout.addWidget(self.history_list_widget)
        self.playlist_label = QLabel("播放列表:")
        self.right_panel_layout.addWidget(self.playlist_label)
        self.right_panel_layout.addWidget(self.playlist_list_widget)

        # 最终的水平布局，左右两边
        self.final_layout = QHBoxLayout()
        self.final_layout.addLayout(self.main_v_layout, 3) # 视频和控制区域占据更多空间
        self.final_layout.addLayout(self.right_panel_layout, 1) # 右侧面板占据较少空间

        central_widget = QWidget(self)
        central_widget.setLayout(self.final_layout)
        self.setCentralWidget(central_widget)

        # 确保初始化时控制条是可见的
        self._show_controls()

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.overlay.resize(self.video_frame.size())

    def _connect_signals(self):
        self.open_file_button.clicked.connect(self._handle_open_file)
        self.add_to_playlist_button.clicked.connect(self._handle_add_to_playlist)
        self.play_pause_button.clicked.connect(self.player.play_pause)
        # 将overlay的点击事件连接到显示控制条并重置计时器
        self.overlay.clicked.connect(self.player.play_pause) # 原有的播放/暂停功能
        self.overlay.clicked.connect(self._show_controls_and_reset_timer) # 新增：点击视频区显示控制条
        self.overlay.mouse_moved.connect(self._show_controls_and_reset_timer) # 新增：鼠标移动到视频区显示控制条

        self.stop_button.clicked.connect(self._handle_stop)
        self.prev_button.clicked.connect(self._play_prev_in_playlist)
        self.next_button.clicked.connect(self._play_next_in_playlist)
        self.position_slider.sliderMoved.connect(self._handle_set_position)
        self.volume_slider.valueChanged.connect(self.player.set_volume)

        # 列表项双击事件
        self.history_list_widget.itemDoubleClicked.connect(self._handle_play_from_history)
        self.playlist_list_widget.itemDoubleClicked.connect(self._handle_play_from_playlist)

        # 播放器核心信号
        self.player.position_changed.connect(self.position_slider.setValue)
        self.player.time_changed.connect(self.time_label.setText)
        self.player.media_ended.connect(self._handle_media_ended)
        self.player.playback_state_changed.connect(self._update_play_pause_icon)

    def _create_shortcuts(self):
        """创建全局快捷键"""
        QShortcut(QKeySequence(Qt.Key.Key_Space), self, self.player.play_pause)
        QShortcut(QKeySequence("F"), self, self.toggle_fullscreen)
        QShortcut(QKeySequence(Qt.Key.Key_Right), self, lambda: self.player.seek_relative(5000)) # 快进5秒
        QShortcut(QKeySequence(Qt.Key.Key_Left), self, lambda: self.player.seek_relative(-5000)) # 快退5秒
        QShortcut(QKeySequence(Qt.Key.Key_Up), self, self._volume_up)
        QShortcut(QKeySequence(Qt.Key.Key_Down), self, self._volume_down)
        QShortcut(QKeySequence(Qt.Key.Key_N), self, self._play_next_in_playlist) # N键下一曲
        QShortcut(QKeySequence(Qt.Key.Key_P), self, self._play_prev_in_playlist) # P键上一曲

    def _load_stylesheet(self):
        """加载外部QSS样式文件"""
        # 确保路径正确，并且在main.py中已经设置了QCoreApplication的组织名和应用名
        qss_path = os.path.join(os.path.dirname(__file__), "../assets/styles.qss")
        try:
            with open(qss_path, "r", encoding="utf-8") as f:
                self.setStyleSheet(f.read())
        except FileNotFoundError:
            print(f"Stylesheet '{qss_path}' not found. Using default style.")

    def eventFilter(self, source: QObject, event: QEvent) -> bool:
        """
        事件过滤器，仅用于捕获视频帧的双击事件，因为鼠标移动事件现在由ClickableOverlay发出。
        """
        if source is self.video_frame and event.type() == QEvent.Type.MouseButtonDblClick:
            self.toggle_fullscreen()
            return True # 消费掉这个事件
        return super().eventFilter(source, event)

    def _volume_up(self):
        """增加音量辅助方法"""
        new_volume = min(self.player.get_volume() + 5, 100)
        self.player.set_volume(new_volume)
        self.volume_slider.setValue(new_volume)
        self._show_controls_and_reset_timer() # 音量改变时也显示控制条

    def _volume_down(self):
        """减小音量辅助方法"""
        new_volume = max(self.player.get_volume() - 5, 0)
        self.player.set_volume(new_volume)
        self.volume_slider.setValue(new_volume)
        self._show_controls_and_reset_timer() # 音量改变时也显示控制条

    def _show_controls(self):
        """显示控制条"""
        if not self._controls_visible:
            self.controls_container.show() # 显示整个控制条容器
            self._controls_visible = True

    def _hide_controls(self):
        """隐藏控制条"""
        # 只有当控制条当前可见、正在播放且处于全屏模式时才执行隐藏操作
        if self._controls_visible and self.player.is_playing() and self.isFullScreen():
            self.controls_container.hide() # 隐藏整个控制条容器
            self._controls_visible = False

    def _show_controls_and_reset_timer(self):
        """显示控制条并重置隐藏计时器"""
        self._show_controls()
        # 只有在全屏模式且正在播放时才启动隐藏计时器
        if self.isFullScreen() and self.player.is_playing():
            self._hide_controls_timer.start()
        else:
            self._hide_controls_timer.stop() # 非全屏或未播放时停止计时器

    def toggle_fullscreen(self):
        if self.isFullScreen():
            self.showNormal()
            # 退出全屏时显示历史记录和播放列表及其标签，并恢复布局比例
            self.history_label.show()
            self.history_list_widget.show()
            self.playlist_label.show()
            self.playlist_list_widget.show()
            # 恢复主窗口模式下的控制条显示（不再自动隐藏）
            self._show_controls() # 显示控制条容器
            self.final_layout.setStretch(0, 3) # 恢复主视频区域的拉伸因子
            self.final_layout.setStretch(1, 1) # 恢复右侧面板的拉伸因子
            self._hide_controls_timer.stop() # 退出全屏后停止自动隐藏计时器
        else:
            self.showFullScreen()
            # 进入全屏时隐藏历史记录和播放列表及其标签，以及打开和添加到播放列表按钮，并调整布局比例
            self.history_label.hide()
            self.history_list_widget.hide()
            self.playlist_label.hide()
            self.playlist_list_widget.hide()
            self.final_layout.setStretch(0, 1) # 让主视频区域占据全部空间
            self.final_layout.setStretch(1, 0) # 右侧面板不占据空间
            # 进入全屏时，启动自动隐藏计时器
            if self.player.is_playing(): # 只有在播放时才启动隐藏计时器
                self._hide_controls_timer.start()


    def _save_window_state(self):
        """保存窗口大小和位置"""
        self.settings.setValue("geometry", self.saveGeometry())
        self.settings.setValue("windowState", self.saveState())

    def _restore_window_state(self):
        """恢复窗口大小和位置"""
        geometry = self.settings.value("geometry")
        if geometry:
            self.restoreGeometry(geometry)
        state = self.settings.value("windowState")
        if state:
            self.restoreState(state)
        else:
            self.resize(1000, 600) # 默认大小

    def showEvent(self, event):
        super().showEvent(event)
        # 在窗口显示后设置视频输出句柄
        self.player.set_hwnd(self.video_frame.winId())

    def closeEvent(self, event):
        self._save_window_state()
        self.player.stop()
        self.db.close()
        event.accept()

    def _handle_open_file(self):
        filepath, _ = QFileDialog.getOpenFileName(
            self, "选择媒体文件", os.path.expanduser('~'), "媒体文件 (*.mp4 *.mkv *.avi *.mp3 *.flac *.mov)"
        )
        if filepath:
            self._start_playback(filepath)
            self._show_controls_and_reset_timer() # 打开文件后显示控制条并重置计时器
            # 打开文件时不再自动添加到播放列表，用户需要手动点击按钮
            # self.db.add_to_playlist(filepath)
            # self.load_playlist_ui()

    def _handle_add_to_playlist(self):
        filepaths, _ = QFileDialog.getOpenFileNames(
            self, "选择要添加到播放列表的媒体文件", os.path.expanduser('~'), "媒体文件 (*.mp4 *.mkv *.avi *.mp3 *.flac *.mov)"
        )
        if filepaths:
            for filepath in filepaths:
                if self.db.add_to_playlist(filepath):
                    print(f"Added to playlist: {filepath}")
                else:
                    print(f"Already in playlist: {filepath}")
            self.load_playlist_ui() # 刷新播放列表UI
            self._show_controls_and_reset_timer() # 添加到播放列表后显示控制条并重置计时器

    def _handle_play_from_history(self, item):
        filepath = item.data(Qt.ItemDataRole.UserRole)
        if filepath and os.path.exists(filepath):
            self._start_playback(filepath)
            self._show_controls_and_reset_timer() # 播放历史文件后显示控制条并重置计时器
        else:
            self.history_list_widget.takeItem(self.history_list_widget.row(item))
            if filepath:
                self.db.delete_history(filepath)
            print(f"Error: File not found in history: {filepath}. Removed from history.")

    def _handle_play_from_playlist(self, item):
        filepath = item.data(Qt.ItemDataRole.UserRole)
        if filepath and os.path.exists(filepath):
            # 找到当前播放的文件在播放列表中的索引
            try:
                self._current_playlist = self.db.get_playlist() # 刷新当前播放列表
                self._current_playlist_index = self._current_playlist.index(filepath)
                self._start_playback(filepath)
                self._show_controls_and_reset_timer() # 播放播放列表文件后显示控制条并重置计时器
            except ValueError:
                print(f"Error: File '{filepath}' not found in current playlist.")
        else:
            self.playlist_list_widget.takeItem(self.playlist_list_widget.row(item))
            if filepath:
                self.db.remove_from_playlist(filepath)
            print(f"Error: File not found in playlist: {filepath}. Removed from playlist.")
            self.load_playlist_ui() # 刷新播放列表UI

    def _start_playback(self, filepath):
        """开始播放媒体文件，并更新历史记录和播放列表选中状态"""
        self.player.play_media(filepath)
        self.db.add_or_update_history(filepath) # 无论从哪里播放，都更新历史记录
        self.load_history_ui() # 刷新历史记录UI

        # 更新播放列表的选中状态
        try:
            self._current_playlist = self.db.get_playlist() # 确保_current_playlist是最新的
            self._current_playlist_index = self._current_playlist.index(filepath)
            self.playlist_list_widget.setCurrentRow(self._current_playlist_index) # 高亮当前播放的项
        except ValueError:
            # 如果当前播放的文件不在播放列表中，则清除播放列表的选中状态
            self._current_playlist_index = -1
            self.playlist_list_widget.clearSelection()


    def _handle_stop(self):
        self.player.stop()
        self.time_label.setText("00:00:00 / 00:00:00")
        self.position_slider.setValue(0)
        self._current_playlist_index = -1 # 停止时重置播放列表索引
        self._show_controls() # 停止时始终显示控制条
        self._hide_controls_timer.stop() # 停止播放后停止自动隐藏计时器
        self.playlist_list_widget.clearSelection() # 停止时也清除播放列表的选中状态


    def _handle_set_position(self, position):
        self.player.set_position(position / 1000.0)
        self._show_controls_and_reset_timer() # 拖动进度条时也显示控制条

    def _handle_media_ended(self):
        """媒体播放结束时的处理逻辑，自动播放下一曲"""
        print("Media ended.")
        if self._current_playlist_index != -1 and self._current_playlist:
            # 尝试播放下一曲
            self._play_next_in_playlist()
            self._show_controls_and_reset_timer() # 播放下一曲时显示控制条并重置计时器
        else:
            # 如果没有播放列表或播放列表已结束，则停止
            self._handle_stop()


    def _update_play_pause_icon(self, is_playing: bool):
        style = self.style()
        if is_playing:
            self.play_pause_button.setIcon(style.standardIcon(QStyle.StandardPixmap.SP_MediaPause))
            if self.isFullScreen(): # 全屏播放时启动隐藏计时器
                self._hide_controls_timer.start()
        else:
            self.play_pause_button.setIcon(style.standardIcon(QStyle.StandardPixmap.SP_MediaPlay))
            self._hide_controls_timer.stop() # 暂停时停止隐藏计时器
        self._show_controls() # 播放状态改变时显示控制条


    def load_history_ui(self):
        self.history_list_widget.clear()
        history_records = self.db.get_all_history()
        for filepath in history_records:
            item = QListWidgetItem(os.path.basename(filepath))
            item.setData(Qt.ItemDataRole.UserRole, filepath)
            item.setToolTip(filepath)
            self.history_list_widget.addItem(item)

    def load_playlist_ui(self):
        self.playlist_list_widget.clear()
        self._current_playlist = self.db.get_playlist() # 更新内部播放列表
        for filepath in self._current_playlist:
            item = QListWidgetItem(os.path.basename(filepath))
            item.setData(Qt.ItemDataRole.UserRole, filepath)
            item.setToolTip(filepath)
            self.playlist_list_widget.addItem(item)

        # 突出显示当前播放的项（如果存在且在播放列表中）
        if self._current_playlist_index != -1 and self._current_playlist_index < len(self._current_playlist):
            self.playlist_list_widget.setCurrentRow(self._current_playlist_index)
        else:
            # 如果当前播放的文件不在播放列表中，确保没有高亮
            self.playlist_list_widget.clearSelection()


    def _play_next_in_playlist(self):
        if not self._current_playlist:
            return

        if self._current_playlist_index == -1: # 如果当前没有播放文件，从列表第一个开始
            self._current_playlist_index = 0
        else:
            self._current_playlist_index = (self._current_playlist_index + 1) % len(self._current_playlist) # 循环播放

        next_filepath = self._current_playlist[self._current_playlist_index]
        if os.path.exists(next_filepath):
            self._start_playback(next_filepath)
            self.playlist_list_widget.setCurrentRow(self._current_playlist_index) # 突出显示当前播放的项
            self._show_controls_and_reset_timer() # 播放下一曲时显示控制条并重置计时器
        else:
            print(f"Warning: File not found for next in playlist: {next_filepath}. Removing it.")
            self.db.remove_from_playlist(next_filepath)
            self.load_playlist_ui()
            # 移除后重新尝试播放下一曲（可能会导致递归，但通常会处理掉损坏的链接）
            self._play_next_in_playlist()


    def _play_prev_in_playlist(self):
        if not self._current_playlist:
            return

        if self._current_playlist_index == -1: # 如果当前没有播放文件，从列表最后一个开始
            self._current_playlist_index = len(self._current_playlist) - 1
        else:
            self._current_playlist_index = (self._current_playlist_index - 1 + len(self._current_playlist)) % len(self._current_playlist) # 循环播放

        prev_filepath = self._current_playlist[self._current_playlist_index]
        if os.path.exists(prev_filepath):
            self._start_playback(prev_filepath)
            self.playlist_list_widget.setCurrentRow(self._current_playlist_index) # 突出显示当前播放的项
            self._show_controls_and_reset_timer() # 播放上一曲时显示控制条并重置计时器
        else:
            print(f"Warning: File not found for previous in playlist: {prev_filepath}. Removing it.")
            self.db.remove_from_playlist(prev_filepath)
            self.load_playlist_ui()
            # 移除后重新尝试播放上一曲
            self._play_prev_in_playlist()

    def _show_history_context_menu(self, pos):
        """显示历史记录的右键菜单"""
        item = self.history_list_widget.itemAt(pos)
        if item:
            menu = QMenu(self)
            play_action = menu.addAction("播放")
            remove_action = menu.addAction("从历史记录中删除")

            action = menu.exec(self.history_list_widget.mapToGlobal(pos))

            if action == play_action:
                self._handle_play_from_history(item)
            elif action == remove_action:
                filepath = item.data(Qt.ItemDataRole.UserRole)
                if filepath:
                    self.db.delete_history(filepath)
                    self.load_history_ui()

    def _show_playlist_context_menu(self, pos):
        """显示播放列表的右键菜单"""
        item = self.playlist_list_widget.itemAt(pos)
        menu = QMenu(self)

        add_files_action = menu.addAction("添加文件到播放列表")
        clear_playlist_action = menu.addAction("清空播放列表")

        if item:
            play_action = menu.addAction("播放")
            remove_action = menu.addAction("从播放列表中删除")
            menu.addSeparator() # 分隔线

        action = menu.exec(self.playlist_list_widget.mapToGlobal(pos))

        if action == add_files_action:
            self._handle_add_to_playlist()
        elif action == clear_playlist_action:
            self.db.clear_playlist()
            self.load_playlist_ui()
            self._handle_stop() # 清空播放列表后停止播放
        elif item and action == play_action:
            self._handle_play_from_playlist(item)
        elif item and action == remove_action:
            filepath = item.data(Qt.ItemDataRole.UserRole)
            if filepath:
                self.db.remove_from_playlist(filepath)
                self.load_playlist_ui()
                # 如果当前播放的文件被删除，则停止
                if self.player.is_playing() and self.player.get_media().get_mrl().replace('file:///', '') == filepath:
                    self._handle_stop()